package com.jy.rhin.application.assembler;

import cn.org.chiss.rhin._2015.base.Integer;
import cn.org.chiss.rhin._2015.base.*;
import cn.org.chiss.rhin._2015.base.document.Author;
import cn.org.chiss.rhin._2015.base.document.Document;
import cn.org.chiss.rhin._2015.base.document.DocumentEntry;
import cn.org.chiss.rhin._2015.base.document.SubmissionSet;
import cn.org.chiss.rhin._2015.base.object.*;
import cn.org.chiss.rhin._2015.document.repository.ProvideAndRegisterDocumentSet;
import com.jy.api.misc.MiscAPI;
import com.jy.api.misc.dto.DaiMaDto;
import com.jy.framework.base.utils.DateUtil;
import com.jy.rhin.sdk.dto.document.cda.ClinicalDocumentData;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
import java.util.*;
import java.lang.String;
@Component
public class CdaAssembler {
	
	/*@Autowired
	private HospitalAPI hospitalAPI;*/
	@Resource
	private MiscAPI miscApi;
	public  ProvideAndRegisterDocumentSet documentDataToCdaWSData(ClinicalDocumentData data){
		 ProvideAndRegisterDocumentSet message = new ProvideAndRegisterDocumentSet();
		 message.setSubmissionSet(getSubmissionSet(data));
		 message.setDocument(getDocument(data));
		 return message;
	}
	
	public  List<Document> getDocument(ClinicalDocumentData data){
		List<Document> documents = new ArrayList<Document>();
		Document d = new Document();
		d.setContent(data.getContent());
		d.setId(new URI().setValue(data.getId()));
		documents.add(d);
		return documents;
	}
	public  Identifier getPatientId(ClinicalDocumentData data){
		return new Identifier().setValue(new ID().setValue(data.getEid())).setSystem(new URI().setValue(data.getAppid()));
	}
	
	
	public  SubmissionSet getSubmissionSet(ClinicalDocumentData data){
		SubmissionSet s = new SubmissionSet();
		MainID id = new MainID();
		id.setValue(UUID.randomUUID().toString());
		id.setSystem("1");
		s.setId(id);
		s.setStatusCode(new ObjectStatus().setValue(ObjectStatusPrimitive.NEW));
		s.setUniqueId(new OID().setValue(UUID.randomUUID().toString()));
		s.setSubmissionTime(new DateTime().setValue(DateUtil.getNowTimeByFormat("yyyy-MM-dd HH:mm:ss")));
		s.setPatientId(getPatientId(data));
		s.setTitle(new cn.org.chiss.rhin._2015.base.String().setValue(data.getTitle()));
		List<Author> authors = new ArrayList<Author>();
		authors.add(getAuthor(data));
		s.setAuthor(authors);
		s.setSourceId(getSourceId(data));
		s.setContentTypeCode(getClassCode(data));
		List<RegObject> folderOrDocumentEntryOrAssociation = new ArrayList<RegObject>();
		/*Folder f = getFolder(data);
		folderOrDocumentEntryOrAssociation.add(f);*/
		DocumentEntry e = getEntry(data);
		folderOrDocumentEntryOrAssociation.add(e);
		/*folderOrDocumentEntryOrAssociation.add(getAssociation(data,f.getId().getValue(),e.getId().getValue()));
		*/
		s.setFolderOrDocumentEntryOrAssociation(folderOrDocumentEntryOrAssociation);
		return s;
	}
	
	public  OID getSourceId(ClinicalDocumentData data){
		//TODO 文档源标识符，用于确定该提交集由哪一个系统提交。
		return new OID().setValue("1.2.4.333.692.68.7163.275");
	}
	
	public   Author getAuthor(ClinicalDocumentData data){
		Author author = new Author();
		author.setAuthorPerson(new Reference().setReference(new Identifier()
				.setValue(new ID().setValue(data.getAuthor().getName()))));
		List<Reference> authorInstitution = new ArrayList<Reference>();
		Reference r = new Reference();
		r.setReference(new Identifier().setValue(new ID().setValue(data.getCustodian().getId())));
		r.setDisplay(new cn.org.chiss.rhin._2015.base.String().setValue(data.getCustodian().getName()));
		authorInstitution.add(r);
		author.setAuthorInstitution(authorInstitution);
		return author;
	}
	
	/*public  Folder getFolder(ClinicalDocumentData data){
		Folder folder = new Folder();
		MainID id = new MainID();
		id.setValue(UUID.randomUUID().toString());
		folder.setId(id);
		folder.setStatusCode(new ObjectStatus().setValue(ObjectStatusPrimitive.NEW));
		folder.setClassCode(getClassCode(data));
		folder.setTitle(new cn.org.chiss.rhin._2015.base.String().setValue(data.getTitle()));
		folder.setUniqueId(new OID().setValue(data.getId()));
		folder.setLastUpdateTime(new DateTime().setValue(DateUtil.getNowTimeByFormat("yyyy-MM-dd HH:mm:ss")));
		folder.setPatientId(getPatientId(data));
		List<CodeableConcept> typeCodes = new ArrayList<CodeableConcept>();
		typeCodes.add(getTypeCode(data));
		folder.setTypeCode(typeCodes);
		folder.setHomeCommunityId(getHomeCommunityId(data));
		return folder;
	}*/
	
	public  List<Telecom> getTelecom(ClinicalDocumentData data){
		List<Telecom> telecoms = new ArrayList<Telecom>();
		Telecom t = new Telecom();
		t.setValue(new cn.org.chiss.rhin._2015.base.String().setValue(data.getPatientRole().getTelecom()));
		return telecoms;
	}
	
	public  List<HumanName> getName(ClinicalDocumentData data){
		List<HumanName> names = new ArrayList<HumanName>();
		HumanName n = new HumanName();
		n.setValue(data.getPatientRole().getPatient().getName());
		names.add(n);
		return names;
	}
	
	public  List<Identifier> getIdentifier(ClinicalDocumentData data){
		List<Identifier> ids = new ArrayList<Identifier>();
		Identifier t = new Identifier();
		t.setValue(new ID().setValue(data.getPatientRole().getPatient().getId()));
		ids.add(t);
		return ids;
	}
	
	public  CodeableConcept getClassCode(ClinicalDocumentData data){
		List<Coding> codings = new ArrayList<Coding>();
		Coding c = new Coding();
		c.setDisplay(new cn.org.chiss.rhin._2015.base.String().setValue("健康档案"));
		c.setCode(new Code().setValue("ehr"));
		c.setSystem(new URI().setValue("SD01.01.003.00"));
		c.setSystemName(new cn.org.chiss.rhin._2015.base.String().setValue("文档的粗粒度分类"));
		c.setVersion(new cn.org.chiss.rhin._2015.base.String().setValue("1"));
		codings.add(c);
		return new CodeableConcept().setCoding(codings);
	}
	
	public  Coding getConfidentialityCode(ClinicalDocumentData data){
		Coding c = new Coding();
		c.setDisplay(new cn.org.chiss.rhin._2015.base.String().setValue("public"));
		c.setCode(new Code().setValue("4"));
		c.setSystem(new URI().setValue("2.16.156.10011.2.4.1.4"));
		c.setSystemName(new cn.org.chiss.rhin._2015.base.String().setValue("访问权限代码表"));
		c.setVersion(new cn.org.chiss.rhin._2015.base.String().setValue("1"));
		return c;
	}
	
	public  CodeableConcept getHealthcareFacilityTypeCode(ClinicalDocumentData data/*,HospitalDTO hospital*/){
		List<Coding> codings = new ArrayList<Coding>();
		Coding c = new Coding();
		/*String jingJiLX = "";
		JSONArray array = JSONArray.parseArray(hospital.getExtInfo());
		for(int i=0;i<array.size();i++){
			if("经济类型".equals(array.getJSONObject(i).getString("label"))){
				jingJiLX = array.getJSONObject(i).getString("value");
				break;
			}
		}
		Collection<DaiMaDto> list = miscApi.getDaiMaByZJBSF("GB/T 12402").getData().getDaiMaVoList();
		for(DaiMaDto d :list){
			if(d.getCode().equals(jingJiLX)){
				c.setDisplay(new cn.org.chiss.rhin._2015.base.String().setValue(d.getValue()));
			}
		}*/
		c.setDisplay(new cn.org.chiss.rhin._2015.base.String().setValue("国有全资"));
		c.setCode(new Code().setValue("110"));
		c.setSystem(new URI().setValue("2.16.156.10011.2.3.4.6"));
		c.setSystemName(new cn.org.chiss.rhin._2015.base.String().setValue("经济类型分类与代码"));
		c.setVersion(new cn.org.chiss.rhin._2015.base.String().setValue("1"));
		codings.add(c);
		return new CodeableConcept().setCoding(codings);
	}
	
	public  CodeableConcept getPracticeSettingCode(ClinicalDocumentData data/*,HospitalDTO hospital*/){

		List<Coding> codings = new ArrayList<Coding>();
		Coding c = new Coding();
		/*Collection<DaiMaDto> list = miscApi.getDaiMaByZJBSF("CVX_JGFLGLLB").getData().getDaiMaVoList();
		for(DaiMaDto d :list){
			if(d.getCode().equals(""+hospital.getYiYuanJYXZ())){
				c.setDisplay(new cn.org.chiss.rhin._2015.base.String().setValue(d.getValue()));
			}
		}*/
		c.setDisplay(new cn.org.chiss.rhin._2015.base.String().setValue("非盈利性医疗机构"));
		c.setCode(new Code().setValue(/*""+hospital.getYiYuanJYXZ())*/"1"));
		c.setSystem(new URI().setValue("2.16.156.10011.2.3.4.4"));
		c.setSystemName(new cn.org.chiss.rhin._2015.base.String().setValue("机构分类管理类别代码"));
		c.setVersion(new cn.org.chiss.rhin._2015.base.String().setValue("1"));
		codings.add(c);
		return new CodeableConcept().setCoding(codings);

	}
	
	
	public  DocumentEntry getEntry(ClinicalDocumentData data){
		DocumentEntry e = new DocumentEntry();
		MainID id = new MainID();
		id.setValue(data.getId());
		id.setSystem("1");
		e.setId(id);
		e.setStatusCode(new ObjectStatus().setValue(ObjectStatusPrimitive.NEW));
		e.setClassCode(getClassCode(data));
		e.setLanguageCode(new Code().setValue("zh-CN"));
		e.setConfidentialityCode(getConfidentialityCode(data));
		e.setTitle(new cn.org.chiss.rhin._2015.base.String().setValue(data.getTitle()));
		e.setCreationTime(new DateTime().setValue(data.getEffectiveTime()));
		e.setMimeType(new cn.org.chiss.rhin._2015.base.String().setValue("1"));
		e.setFormatCode(new Code().setValue("urn:formatType:sd:2022"));
		e.setPatientId(getPatientId(data));
		e.setSourcePatientInfo(new Patient().setAssignedPerson(new Person()
				.setTelecom(getTelecom(data))
				.setName(getName(data))
				.setIdentifier(getIdentifier(data))));
		e.setAuthor(getAuthor(data));
		/*HospitalDTO hospital = hospitalAPI.infoByOutId(data.getCustodian().getId()).getData();
		if(hospital == null){
			throw new RuntimeException("当前机构不存在,请维护机构信息");
		}*/
		e.setHealthcareFacilityTypeCode(getHealthcareFacilityTypeCode(data));
		e.setPracticeSettingCode(getPracticeSettingCode(data));
		e.setTypeCode(getTypeCode(data));
		e.setUniqueId(new OID().setValue(UUID.randomUUID().toString()));
		e.setRepositoryUniqueId(getSourceId(data));
		e.setHomeCommunityId(getHomeCommunityId(data));
		String hash = sign(data.getContent());
		e.setHash(new cn.org.chiss.rhin._2015.base.String().setValue(hash));
		e.setSize(new Integer().setValue(data.getContent().length));
		return e;
	}
	
	public  String sign(byte[] bytes) {
        if (Objects.isNull(bytes) || bytes.length == 0) {
            return null;
        }

        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(bytes);
            byte[] md = mdTemp.digest();
            int j = md.length;
            char[] buf = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(buf);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("文档内容hash异常");
        }
    }
	public  OID getHomeCommunityId(ClinicalDocumentData data){
		return null;
	}
	
	public  CodeableConcept getTypeCode(ClinicalDocumentData data){
		List<Coding> codings = new ArrayList<Coding>();
		Coding c = new Coding();
		Collection<DaiMaDto> list = miscApi.getDaiMaByZJBSF("SD01.01.002.00").getData().getDaiMaVoList();
		c.setDisplay(new cn.org.chiss.rhin._2015.base.String().setValue(list.stream().filter(d->d.getCode().equals(data.getTemplateId())).findFirst().orElse(null).getValue()));
		c.setCode(new Code().setValue(data.getTemplateId()));
		c.setSystem(new URI().setValue("2.16.156.10011.2.4.1.1"));
		c.setSystemName(new cn.org.chiss.rhin._2015.base.String().setValue("文档的细粒度分类"));
		c.setVersion(new cn.org.chiss.rhin._2015.base.String().setValue("1"));
		codings.add(c);
		return new CodeableConcept().setCoding(codings);
	}
	
	
	/*public  Association getAssociation(ClinicalDocumentData data,String sourceId,String targetId){
		Association a = new Association();
		MainID id = new MainID();
		id.setValue(UUID.randomUUID().toString());
		a.setId(id);
		a.setStatusCode(new ObjectStatus().setValue(ObjectStatusPrimitive.NEW));
		a.setTypeCode(new AssociationType().setValue(""));
		a.setSourceObject(new AssociationObject().setId(new URI().setValue(sourceId))
				.setStatus(new AssociationStatus().setValue(AssociationStatusPrimitive.ORIGINAL)));
		a.setTargetObject(new AssociationObject().setId(new URI().setValue(targetId))
				.setStatus(new AssociationStatus().setValue(AssociationStatusPrimitive.ORIGINAL)));
		return a;
	}*/
	
	
	public static void main(String[] args) {
		System.out.println(UUID.randomUUID());
	}
	
	
}
